package cn.xshi.common.util;

import cn.xshi.common.constant.CacheConstant;
import cn.xshi.common.base.BaseRestUrl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.*;

/**
 * @Desc restTemplate工具类(非微服务LoadBalanced，用于非微服务调用)
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
public class GlobalRestTemplateUtil extends BaseRestUrl {

    @Resource(name = "globalRestTemplate")
    RestTemplate globalRestTemplate;
    public HttpHeaders setHeaders(HttpServletRequest request){
        HttpHeaders headers = new HttpHeaders();
        if(null == request){
            return headers;
        }
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            headers.add(key, value);
        }

        //TODO 设置秘钥
        Map<String,String> map = new HashMap<>();
        map.put(CacheConstant.JEHC_CLOUD_KEY,getJehcCloudKey());
        map.put(CacheConstant.JEHC_CLOUD_SECURITY,getJehcCloudSecurity());
        Set<String> keys  = map.keySet();
        Iterator<String> iteratorK = keys.iterator();
        while (iteratorK.hasNext()) {
            String key = (String) iteratorK.next();
            if(null == key){
                continue;
            }
            headers.add(key,map.get(key));
        }
        return headers;
    }


    /**
     * set Headers By mxy
     * @param request
     * @param key_
     * @param val
     * @return
     */
    public HttpHeaders setHeaders(HttpServletRequest request,String key_,String val){
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            headers.add(key, value);
        }
        headers.add(key_,val);
        //TODO 设置秘钥
        Map<String,String> map = new HashMap<>();
        map.put(CacheConstant.JEHC_CLOUD_KEY,getJehcCloudKey());
        map.put(CacheConstant.JEHC_CLOUD_SECURITY,getJehcCloudSecurity());
        Set<String> keys  = map.keySet();
        Iterator<String> iteratorK = keys.iterator();
        while (iteratorK.hasNext()) {
            String key = (String) iteratorK.next();
            if(null == key){
                continue;
            }
            headers.add(key,map.get(key));
        }
        return headers;
    }

    /**
     * set Headers By dengcj
     * @param request
     * @param kvMap
     * @return
     */
    public HttpHeaders setHeaders(HttpServletRequest request,Map<String,String> kvMap){
        HttpHeaders headers = new HttpHeaders();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            headers.add(key, value);
        }
        Set<String> keys  = kvMap.keySet();
        Iterator<String> iteratorK = keys.iterator();
        while (iteratorK.hasNext()) {
            String key = (String) iteratorK.next();
            if(null == key){
                continue;
            }
            headers.add(key,kvMap.get(key));
        }

        //TODO 设置秘钥
        Map<String,String> map = new HashMap<>();
        map.put(CacheConstant.JEHC_CLOUD_KEY,getJehcCloudKey());
        map.put(CacheConstant.JEHC_CLOUD_SECURITY,getJehcCloudSecurity());
        Set<String> keys1  = map.keySet();
        Iterator<String> iteratorK1 = keys1.iterator();
        while (iteratorK1.hasNext()) {
            String key = (String) iteratorK1.next();
            if(null == key){
                continue;
            }
            headers.add(key,map.get(key));
        }
        return headers;
    }

    /**
     * Get（Does not contain input parameters）
     * @param url
     * @param request
     * @return
     */
    public String get(String url,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
        ResponseEntity<String> response = globalRestTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        if(null != response){
            return response.getBody();
        }
        return null;
    }

    /**
     * Get（Does not contain input parameters）
     * @param url
     * @param request
     * @return
     */
    public <T> T get(String url,Class<T> out,HttpServletRequest request) {
        HttpHeaders httpHeaders = null;
        if(null != request){
            httpHeaders = setHeaders(request);
        }
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }

    /**
     * Get（Does not contain input parameters）
     * @param url
     * @param request
     * @return
     */
    public <T> T get(String url,Class<T> out,HttpServletRequest request,HttpHeaders headers) {
        HttpHeaders httpHeaders = null;
        if(null != request){
            httpHeaders = setHeaders(request);
            httpHeaders.addAll(headers);
        }
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }
    /**
     * Get（Does not contain input parameters）
     * @param url
     * @param headers
     * @return
     */
    public <T> T getUnRequest(String url,Class<T> out,HttpHeaders headers) {
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, headers);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }

//
//	/**
//	 * Get（Contains input parameters）
//	 * @param url
//	 * @param request
//	 * @return
//	 */
//	public <T> T get(String url,Class<T> out,Object input,HttpServletRequest request) {
//		HttpHeaders httpHeaders = setHeaders(request);
//		httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//		httpHeaders.add("Accept", "*/*");
//		List<MediaType> acceptableMediaTypes = new ArrayList<>();
//		acceptableMediaTypes.add(MediaType.ALL);
//		httpHeaders.setAccept(acceptableMediaTypes);
//		HttpEntity<Object> httpEntity = new HttpEntity<Object>(input, httpHeaders);
//		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
//		if(null != response){
//			return response.getBody();
//		}
//		return null;
//	}

    /**
     * post Request, including path, return type, Header, Parameter
     * @param url
     * @param out
     * @param header
     * @param input
     * @param jsonBody
     * @return
     */
    public <T> T post(String url, Class<T> out, Map<String, Object> header,Object input, String jsonBody,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        if (header != null) {
            Set<String> keys = header.keySet();
            for (Iterator<String> i = keys.iterator(); i.hasNext();) {
                String key = (String) i.next();
                httpHeaders.add(key, header.get(key).toString());
            }
        }
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.add("Accept", "*/*");
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<Object> formEntity = new HttpEntity<Object>(jsonBody, httpHeaders);
        return globalRestTemplate.postForObject(url, formEntity, out, input);
    }

    /**
     * post（Contains input parameters）
     * @param url
     * @param out
     * @param input
     * @return
     */
    public <T> T post(String url, Class<T> out,Object input) {
        HttpHeaders httpHeaders = setHeaders(null);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.add("Accept", "*/*");
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
        return globalRestTemplate.postForObject(url, formEntity, out);
    }

    /**
     * post（Contains input parameters）
     * @param url
     * @param out
     * @param input
     * @param request
     * @return
     */
    public <T> T post(String url, Class<T> out,Object input,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.add("Accept", "*/*");
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
        return globalRestTemplate.postForObject(url, formEntity, out);
    }

    /**
     * post（Contains input parameters）
     * @param url
     * @param out
     * @param input
     * @return
     */
    public <T> T post(String url, Class<T> out,Object input,HttpHeaders httpHeaders) {
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.add("Accept", "*/*");
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
        return globalRestTemplate.postForObject(url, formEntity, out);
    }

    /**
     * Post（Does not contain any input parameters）
     * @param url
     * @param out
     * @param request
     * @return
     */
    public <T> T post(String url, Class<T> out,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        httpHeaders.add("Accept", "*/*");
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<T> formEntity = new HttpEntity<T>(httpHeaders);
        return globalRestTemplate.postForObject(url, formEntity, out);
    }

    /**
     * post uriVariables
     * @param url
     * @param out
     * @param input
     * @param uriVariables
     * @param request
     * @param <T>
     * @return
     */
    public <T> T post(String url, Class<T> out, Object input,Map<String, Object> uriVariables,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
//		httpHeaders.add("Accept", "*/*");
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
//		acceptableMediaTypes.add(MediaType.ALL);
//		httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
        return globalRestTemplate.postForObject(url, formEntity, out, uriVariables);
    }

    /**
     * post upload file
     * @param url
     * @param out
     * @param input
     * @param request
     * @param <T>
     * @return
     */
    public <T> T post(String url, Class<T> out, MultiValueMap<String, Object> input , HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        httpHeaders.add("Accept", "*/*");
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);

        ClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory();
        globalRestTemplate.setRequestFactory(clientFactory);
        URI uri = UriComponentsBuilder.fromUriString(url).build().encode().toUri();
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(input, httpHeaders);
        ResponseEntity<T> responseEntity = globalRestTemplate.exchange(uri, HttpMethod.POST, httpEntity, out);
        return responseEntity.getBody();
    }

    /**
     * Put
     * @param url
     * @param out
     * @param input
     * @param request
     * @return
     */
    public <T> T put(String url, Class<T> out,Object input,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        httpHeaders.add("Accept", "*/*");
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        List<MediaType> acceptableMediaTypes = new ArrayList<>();
        acceptableMediaTypes.add(MediaType.ALL);
        httpHeaders.setAccept(acceptableMediaTypes);
        HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.PUT, formEntity, out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }


    /**
     * delete（Contains MultiValueMap<String, Object> parameters）
     * @param url
     * @param input （MultiValueMap<String, Object> Type）
     * @param request
     * @return
     */
    public <T> T delete(String url,Class<T> out,Map<String, ?> input,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, ?>> httpEntity = new HttpEntity<Map<String, ?>>(input, httpHeaders);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.DELETE, httpEntity,out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }

    /**
     * delete（Contains the Object parameter）
     * @param url
     * @param input （Object Type）
     * @param request
     * @return
     */
    public <T> T delete(String url,Class<T> out,Object input,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Object> httpEntity = new HttpEntity<Object>(input, httpHeaders);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.DELETE, httpEntity, out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }


    /**
     * delete（Does not contain input parameters）
     * @param url
     * @param request
     * @return
     */
    public <T>T delete(String url,Class<T> out,HttpServletRequest request) {
        HttpHeaders httpHeaders = setHeaders(request);
        HttpEntity<?> httpEntity = new HttpEntity<>(null, httpHeaders);
        ResponseEntity<T> response = globalRestTemplate.exchange(url, HttpMethod.DELETE, httpEntity, out);
        if(null != response){
            return response.getBody();
        }
        return null;
    }

    /**
     *
     * @param url
     * @param request
     * @return
     */
    public byte[] exportForGet(String url,HttpServletRequest request) {
        try {
            ResponseEntity<byte[]> entity = globalRestTemplate.getForEntity(url, byte[].class);
            byte[] bytes = entity.getBody();
            return bytes;
        } catch (Exception e) {
            log.error("下载文件接口调用失败",e);
        }
        return null;
    }

    /**
     *
     * @param url
     * @param request
     * @param headers
     * @return
     */
    public byte[] exportForGet(String url,HttpServletRequest request,HttpHeaders headers) {
        try {
            HttpHeaders httpHeaders = null;
            if(null != request){
                httpHeaders = setHeaders(request);
                httpHeaders.addAll(headers);
            }
            HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
            ResponseEntity<byte[]> entity = globalRestTemplate.getForEntity(url, byte[].class,httpEntity);
            byte[] bytes = entity.getBody();
            return bytes;
        } catch (Exception e) {
            log.error("下载文件接口调用失败",e);
        }
        return null;
    }
}
